//TODO: 1.From :
//  FileBuffers::from_read(Read)
//  FileBuffers::from_path(AsRef<Path>)

//OK 2. Iterator
// summarize 3-class solution for FileBuffers Iterator
// many tips for RefCell, Cell

//3. buffer to collections with IntoIterator impl


/*1.   like std::fs::read_dir() => use read_file_as_buffer().iter().take(10).for_each(...show); 
 *  Reason: Cann't return an ref to Iterator(self)'s member in RUST,  Please use Owner<--Iterator::Item = &'a [u8] pattern
 */

/*
use std::vec::Vec;
use std::path::Path;

fn read_file_as_buffer<P: AsRef<Path>>(path: P, len: usize) -> std::io::Result<FileBuffers> {
    Ok(FileBuffers::new(std::fs::File::open(path)?, len))
}

struct FileBuffers {
    file: std::fs::File,
    buffer: Vec<u8>,
    last: usize,
}
impl std::fmt::Debug for FileBuffers {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "len:{}, buffer:", &self.buffer.len())?;
        self.buffer.fmt(f)
    }
}
impl FileBuffers {
    fn new(file: std::fs::File, len: usize) -> Self {
        Self {
            file,
            buffer: vec![0_u8; len],
            last: 0,
        }
    }
}


impl Iterator for FileBuffers{
    type Item = &'a [u8]; //TODO: 'a ????? 

    fn next(& mut self) -> Option<Self::Item> {
        Some(&self.buffer)
    }
}
*/




/*
use std::io::Read;
struct FileBuffers {
    buffers: Vec<u8>,
    file: std::fs::File,
}
impl FileBuffers {
    fn new(file: std::fs::File, len: usize) -> Self {
        Self {
            file,
            buffers: vec![0_u8;  len],
        }
    }
    fn read_buffer(&mut self) ->std::io::Result<usize> {
        self.file.read(&mut self.buffers)
    }

    fn iter_mut(&mut self) -> IterMut<'_> {
        crate::iterator::IterMut::new(&mut self.buffers, &mut self.file)
    }
}

struct IterMut<'a> {
    buffers: &'a Vec<u8>,
    file: &'a std::fs::File,
}
impl<'a> IterMut<'a> {
    fn new(buffers: &'a mut Vec<u8>, file:&'a mut std::fs::File) -> Self {
        Self {
            buffers,
            file
        }
    }
}
impl<'a> Iterator for IterMut<'a> {
    type Item = &'a [u8];
    fn next(&mut self) -> Option<Self::Item> {
        //self.read_buffer()
        Some(&self.buffers)
        /*
        match self.read_buffer() {
            Ok(len) => { 
                if len == 0 {
                    None
                }
                else{
                    //Some(&self.buffers)
                    //println!("next---> len: {}, buffer: {:?}", len, buffers);
                    //Some(buffers)
                    None
                }
            }
            Err(_) => {
                println!("read buffers error");
                None
                //Some(Err(e))
            }
        }
        */
    }
}
*/


use std::io::Read;
use std::cell::RefCell;

struct FileBuffersWrapper{
    inner: RefCell<std::fs::File>,
    buffers: RefCell<Vec<u8>>,
}
impl FileBuffersWrapper {
    fn new(file: std::fs::File, len: usize) -> Self {
        Self {
            inner: RefCell::new(file),
            buffers: RefCell::new(vec![0_u8; len]),
        }
    }
    fn read_buffer(&self) ->std::io::Result<usize> {
        self.inner.borrow_mut().read(&mut self.buffers.borrow_mut())
    }
    fn get_buffers(&self) -> std::cell::Ref<'_, Vec<u8>> {
        self.buffers.borrow()
    }

    fn iter(&self) -> Iter<'_> {
        crate::iterator::Iter::new(self)
    }
}

struct Iter<'a> {
    file_buffer: &'a FileBuffersWrapper,
}
impl<'a> Iter<'a> {
    fn new(file_buffer: &'a FileBuffersWrapper) -> Self {
        Self {
            file_buffer
        }
    }
}
impl<'a> Iterator for Iter<'a> {
    type Item = (std::cell::Ref<'a, Vec<u8>>, usize);

    fn next(&mut self) -> Option<Self::Item> {
        self.file_buffer
            .read_buffer()
            .map(|len| (self.file_buffer.get_buffers(), len))
            .ok()
            /*
            .map_or(None,
                |len| {
                    if len != 0 {
                        Some((self.file_buffer.get_buffers(), len))
                    } else {
                        None
                    }
            })*/
    }
}

#[cfg(test)]
mod test{
    use super::*;

    #[test]
    fn test_file_buffers() {
        let fname = "./src/agent.rs";
        FileBuffersWrapper::new(std::fs::File::open(fname).unwrap(), 1024)
            .iter()
            .take(1)
            .map(|(b, len)| {
                String::from_utf8_lossy(&b[..len]).to_string()
            })
            .flat_map(|s| { 
                s.chars().collect::<Vec<_>>()
            })
            .for_each(|s|{
                print!("{s}");
            });

    }
    /*
    #[test]
    fn test_file_buffers() -> std::io::Result<()>{
        let fname = "./src/main.rs";

        let fb = FileBuffers::new(std::fs::File::open(fname).unwrap(), 1024);
        println!("{:?}", fb.get_buffers());

        let mut fb = FileBuffers::new(std::fs::File::open(fname).unwrap(), 1024);
        fb.read_buffer()?;
        println!("{:?}", fb.get_buffers());
        Ok(())

    }
    */

    use std::iter::{once, zip};

    fn sum(x : (usize, usize)) -> usize {
        x.0 + x.1
    }

    #[test]
    fn test_map_while(){
        let a = vec![-1i32, 4, 4, 0, 1, 4, 4, 4];

        let mut iter = a.iter().map_while(|x| 16i32.checked_div(*x));

        assert_eq!(iter.next(), Some(-16));
        assert_eq!(iter.next(), Some(4));
        assert_eq!(iter.next(), Some(4));
        assert_eq!(iter.next(), None);

        a.iter().reduce(|acc, e| {
            println!("acc:{acc}, e:{e}");
            e
        });

        a.iter().map(|e| e * 10).nth(1);

        println!("last of iter:{}", once(101).last().unwrap());

        assert!(once(1_usize)
            .map(std::io::Result::<usize>::Ok)
            .next()
            .unwrap() //not None
            .is_ok() // result is ok
        );


        once(1)
            .map(|x| x * 10)
            .for_each( |x| println!("{x}"));

        once((1, 2))
            .for_each(|(x, y)| println!("{x}:{y}"));

        once((10, 20))
            .map(sum)
            .for_each( |x| println!("sum:{x}"));

        zip(once(1), once(2))
            .for_each(|(x, y)| println!("{x}:{y}"));

        a.into_iter()
            .for_each(|v| println!("into_iter:{v}"));
        //println!("..........len:{}", a.len());
        //a.into_iter().for_each(|v| println!("into_iter:{v}"));
        //
    }
    #[test]
    fn test_into_iter() {
        let a = vec![-1i32, 4, 4, 0, 1, 4, 4, 4];
        a.into_iter()
            .for_each(|v| println!("into_iter:{v}"));
        //NOTE: a is consumed by into_iter
        
        let a = vec![-1i32, 4, 4, 0, 1, 4, 4, 4];
        for v in a {
            println!("for loop with vec:{v}");
        }
        // a is consumed by for-loop (a.into_iter)
        // println!("{:?}", a); compile error
        
        let mut a = vec![-1i32, 4, 4, 0, 1, 4, 4, 4];
        //consume the &'a mut vec
        for v in &mut a {
            println!("for loop with &vec:{v}");
        }
        println!("{:?}", a);

        //consume the &'a vec
        for v in & a {
            println!("for loop with &vec:{v}");
        }
        println!("{:?}", a);

        // consume the Iter object of a.iter()
        for v in a.iter() {
            println!("for loop with vec.iter():{v}");
        }
        println!("{:?}", a);


        let c = vec![1, 2 ,3 , 4];
        for mut i in c {
            i += 10;
            println!("for mut i {i}");
        }
        
    }

    #[derive(Debug)]
    struct GtpStrings {
        gtps: Vec<String>,
    }
    impl GtpStrings {
        fn new() -> Self {
            Self {
                gtps: Vec::<String>::new(),
            }
        }
    }

    impl FromIterator<String> for GtpStrings {
        fn from_iter<T>(iter: T) -> Self 
        where T: IntoIterator<Item=String> 
        {
            let mut c = Vec::<String>::new();
            for i in iter {
                c.push(i);
            }
            Self {
                gtps: c
            }
        }
    }
    impl<'a> FromIterator<&'a str> for GtpStrings {
        fn from_iter<T>(iter: T) -> Self 
        where T: IntoIterator<Item=&'a str> 
        {
            let mut c = Vec::<String>::new();
            for i in iter {
                //TODO: validate it
                c.push(i.to_owned());
            }
            Self {
                gtps: c
            }
        }
    }

    #[test]
    fn test_from_iter(){
        let ss = vec!["s1".to_owned(), "s2".to_owned(), "s3".to_owned()];
        let gs = GtpStrings::from_iter(ss);
        println!("gtpString{:?}", gs);

        let gs = GtpStrings::from_iter(["s1", "s2", "s3"]);
        println!("gtpString{:?}", gs);

    }

    impl Extend<String> for GtpStrings {
        fn extend<T: IntoIterator<Item=String>>(&mut self, iter: T) {
            for i in iter {
                self.gtps.push(i);
            }
        }
    }
    impl<'a> Extend<&'a str> for GtpStrings {
        fn extend<T: IntoIterator<Item=&'a str>>(&mut self, iter: T) {
            for i in iter {
                self.gtps.push(i.to_owned());
            }
        }
    }
    
    #[test]
    fn test_extend() {
        let mut gs = GtpStrings::new();
        let ss = vec!["s1".to_owned(), "s2".to_owned(), "s3".to_owned()];
        gs.extend(ss);
        println!("gtpString{:?}", gs);

        gs.extend(["s1", "s2", "s3"]);
        println!("gtpString{:?}", gs);
    }

    impl IntoIterator for GtpStrings {
        type Item = String;
        type IntoIter = std::vec::IntoIter<Self::Item>;
        fn into_iter(self) -> Self::IntoIter {
            self.gtps.into_iter()
        }
    }
    //TODO: IntoIterator implementation
    /*
    impl<'a> IntoIterator for &'a GtpStrings  {
        type Item = &'a str
        type IntoIter = 
        fn into_iter(self) -> Self::IntoIter {
            (&(self.gtps)).into_iter()
        }
    }*/
    #[test]
    fn test_into_iter_impl(){
        let gs = GtpStrings::from_iter(["s1", "s2", "s3"]);
        for i in gs {
            println!("into_iter: {i}");
        }



        /*
        // C::Element is copyable
        let c = Collections::new();
        while let(next) = c.next() { //V is Copyable
            visit（next)
        }

        // C::Element is Movable
        let c = Collections::new();
        while let(next) = c.next() { //V is Movable
            visit（next)
        }

        let c = Collections::new();
        let iter = c.iter(&self)
        while let(ref iter) = iter.next_ref() { //V is ref of Collections copyable
            visit（next)
        }

        let c = Collections::new();
        let iter = c.iter(&self)
        while let(ref mut iter) = iter.next_mut_ref() { //V is ref of Collections copyable
            visit（next)
        }
        */

    }

    #[test]
    fn test_iter_scan() {    
        let buf : [u8; 8] = [7_u8, 7, 7, 0x0a, 4, 5, 7, 0x0a];
        buf.iter()
            .scan((false, 0), |state, &x|{
                if x == 0x0a {
                    *state = (true, state.1 + 1)
                }
                else{
                    *state = (false, state.1 + 1)
                }
                Some(*state)
            })
            .filter(|(flag, _)| *flag == true )
            .map(|(_, v)| v)
            .for_each(|v| println!("{:?}", v))
            ;

        buf.iter()
            .scan((false, 0), |state, &x|{
                if x == 0x0a {
                    *state = (true, state.1 + 1)
                }
                else{
                    *state = (false, state.1 + 1)
                }
                Some(*state)
            })
            .filter_map(|(flag, v)| if flag == true { Some(v) } else { None} )
            .take(1)
            .for_each(|v| println!("{:?}", v))
            ;

        let data: [u8; 10] = [1, 2, 3, 4, 5, 6, 7, 8 , 9 , 10];
        buf.iter()
            //.flat_map(|&v| (0..(v as usize)))
            .flat_map(|v|   &data[0..*v as usize])
            .for_each(|v| println!(".......#####{:?}", v))
            ;
    }
}


